{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "936e5b1c-ce94-45b8-a5e3-e3b2084d0d00",
   "metadata": {},
   "source": [
    "与指定响应模型的方式相同，你也可以在以下任意的路径操作中使用 status_code 参数来声明用于响应的 HTTP 状态码：\r\n",
    "\r\n",
    "@app.get()\r\n",
    "@app.post()\r\n",
    "@app.put()\r\n",
    "@app.delete(\n",
    "\n",
    "注意，status_code 是「装饰器」方法（get，post 等）的一个参数。不像之前的所有参数和请求体，它不属于路径操作函数。)\r\n",
    "等等。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "0b0aa561-d319-461f-8745-d54a54807263",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Started server process [5212]\n",
      "INFO:     Waiting for application startup.\n",
      "INFO:     Application startup complete.\n",
      "INFO:     Uvicorn running on http://0.0.0.0:8009 (Press CTRL+C to quit)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:     127.0.0.1:56632 - \"GET /items?name=foo HTTP/1.1\" 307 Temporary Redirect\n",
      "INFO:     127.0.0.1:56632 - \"GET /items/?name=foo HTTP/1.1\" 405 Method Not Allowed\n",
      "INFO:     127.0.0.1:56641 - \"POST /items?name=foo HTTP/1.1\" 307 Temporary Redirect\n",
      "INFO:     127.0.0.1:56641 - \"POST /items/?name=foo HTTP/1.1\" 201 Created\n",
      "INFO:     127.0.0.1:56664 - \"POST /items?name=foo HTTP/1.1\" 307 Temporary Redirect\n",
      "INFO:     127.0.0.1:56664 - \"POST /items/?name=foo HTTP/1.1\" 201 Created\n",
      "INFO:     127.0.0.1:56668 - \"POST /items?name=foo HTTP/1.1\" 307 Temporary Redirect\n",
      "INFO:     127.0.0.1:56668 - \"POST /items/?name=foo HTTP/1.1\" 201 Created\n",
      "INFO:     127.0.0.1:56669 - \"POST /items?name=foo HTTP/1.1\" 307 Temporary Redirect\n",
      "INFO:     127.0.0.1:56669 - \"POST /items/?name=foo HTTP/1.1\" 201 Created\n",
      "INFO:     127.0.0.1:56684 - \"POST /items?name=foo HTTP/1.1\" 307 Temporary Redirect\n",
      "INFO:     127.0.0.1:56684 - \"POST /items/?name=foo HTTP/1.1\" 201 Created\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Shutting down\n",
      "INFO:     Waiting for application shutdown.\n",
      "INFO:     Application shutdown complete.\n",
      "INFO:     Finished server process [5212]\n"
     ]
    }
   ],
   "source": [
    "import uvicorn\n",
    "from fastapi import FastAPI\n",
    "app = FastAPI()\n",
    "\n",
    "@app.post(\"/items/\", status_code=201)\n",
    "async def create_item(name: str):\n",
    "    return {\"name\": name}\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    config = uvicorn.Config(app, host='0.0.0.0', port=8009)\n",
    "    server = uvicorn.Server(config)\n",
    "    await server.serve()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aa887032-19ff-419e-bd2d-03b160f5ae6e",
   "metadata": {},
   "source": [
    "status_code 参数接收一个表示 HTTP 状态码的数字。\n",
    "\n",
    "status_code 也能够接收一个 IntEnum 类型，比如 Python 的 http.HTTPStatus。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "80bedb08-be91-4c3d-8dba-44287c3fa7a5",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = 'http://127.0.0.1:8009/items?name=foo' \n",
    "res = requests.post(url) \n",
    "print(res.status_code)\n",
    "print(res.text)\n",
    "\n",
    "# 在另一个ipynb文件中运行代码，会得到 \n",
    "# 201\n",
    "# {\"name\":\"foo\"}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "09d2cba0-27c8-43dc-bd00-ac977a24cb7e",
   "metadata": {},
   "source": [
    "它将会：\r\n",
    "\r\n",
    "在响应中返回该状态码。\r\n",
    "在 OpenAPI 模式中（以及在用户界面中）将。录为："
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d35e1c65-1f1b-46d5-aa80-9d8bb297f352",
   "metadata": {},
   "source": [
    "## 关于 HTTP 状态码"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c4b2f798-2528-4597-8c23-683a6b8ec531",
   "metadata": {},
   "source": [
    "在 HTTP 协议中，你将发送 3 位数的数字状态码作为响应的一部分。\r\n",
    "\r\n",
    "这些状态码有一个识别它们的关联名称，但是重要的还是数字。\r\n",
    "\r\n",
    "简而言之：\r\n",
    "\r\n",
    "100 及以上状态码用于「消息」响应。你很少直接使用它们。具有这些状态代码的响应不能带有响应体。\r\n",
    "200 及以上状态码用于「成功」响应。这些是你最常使用的。\r\n",
    "200 是默认状态代码，它表示一切「正常」。\r\n",
    "另一个例子会是 201，「已创建」。它通常在数据库中创建了一条新记录后使用。\r\n",
    "一个特殊的例子是 204，「无内容」。此响应在没有内容返回给客户端时使用，因此该响应不能包含响应体。\r\n",
    "300 及以上状态码用于「重定向」。具有这些状态码的响应可能有或者可能没有响应体，但 304「未修改」是个例外，该响应不得含有响应体。\r\n",
    "400 及以上状态码用于「客户端错误」响应。这些可能是你第二常使用的类型。\r\n",
    "一个例子是 404，用于「未找到」响应。\r\n",
    "对于来自客户端的一般错误，你可以只使用 400。\r\n",
    "500 及以上状态码用于服务器端错误。你几乎永远不会直接使用它们。当你的应用程序代码或服务器中的某些部分出现问题时，它将自动返回这些状态代码之一。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0f59049d-7d99-4c40-b879-61719fb72d07",
   "metadata": {},
   "source": [
    "## 记住名称的捷径"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7575238f-b19a-47e0-ad4f-20bf3232824e",
   "metadata": {},
   "source": [
    "你可以使用来自 fastapi.status 的便捷变量。\n",
    "\n",
    "它们只是一种便捷方式，它们具有同样的数字代码，但是这样使用你就可以使用编辑器的自动补全功能来查找它们。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "0b6a2e0b-b005-45b1-b8af-7a6699e9c79d",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Started server process [5212]\n",
      "INFO:     Waiting for application startup.\n",
      "INFO:     Application startup complete.\n",
      "INFO:     Uvicorn running on http://0.0.0.0:8009 (Press CTRL+C to quit)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:     127.0.0.1:56779 - \"POST /items?name=foo HTTP/1.1\" 307 Temporary Redirect\n",
      "INFO:     127.0.0.1:56779 - \"POST /items/?name=foo HTTP/1.1\" 201 Created\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Shutting down\n",
      "INFO:     Waiting for application shutdown.\n",
      "INFO:     Application shutdown complete.\n",
      "INFO:     Finished server process [5212]\n"
     ]
    }
   ],
   "source": [
    "import uvicorn\n",
    "from fastapi import FastAPI, status\n",
    "app = FastAPI()\n",
    "\n",
    "@app.post(\"/items/\", status_code=status.HTTP_201_CREATED)\n",
    "async def create_item(name: str):\n",
    "    return {\"name\": name}\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    config = uvicorn.Config(app, host='0.0.0.0', port=8009)\n",
    "    server = uvicorn.Server(config)\n",
    "    await server.serve()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fb5d374c-3940-4e72-9803-82eda7b186a4",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = 'http://127.0.0.1:8009/items?name=foo' \n",
    "res = requests.post(url) \n",
    "print(res.status_code)\n",
    "print(res.text)\n",
    "\n",
    "# 在另一个ipynb文件中运行代码，会得到 \n",
    "# 201\n",
    "# {\"name\":\"foo\"}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
